#include <iostream>


using namespace std;

// 类型推导：
    // auto在推导时会忽略顶层const 和引用，保留底层const属性，在编译期间进行类型推导
        // auto 会声明变量，所以auto a;是错误的，编译器不确定其类型
        // 在函数传参时也不能用auto
        // 必须初始化

    //  decltype 类型推导时不声明变量，一般用于推导表达式的类型
        // 可以区分左值和右值
        // 对于右值来说自动推导为基础类型
        // 对于左值来说通过decltype(x)和decltype((x))来确定是引用还是基础类型，后者为引用，前者为基础类型
    
    // result_of
        // 也可以用来推导类型，主要用来模板元编程中推导函数返回值类型
    // invoke_result(c++17)
        // 提供更高效的类型推导
int main(){
    int x=0;
    int * px=&x;
    const int* cpx=&x;
    const int* const cpcx=&x;
    auto ax=x;
    auto apx=px;
    auto acpx=cpx;
    auto acpcx=cpcx;
    cout<<typeid(ax).name()<<endl;
    cout<<typeid(apx).name()<<endl;
    cout<<typeid(acpx).name()<<endl;
    cout<<typeid(acpcx).name()<<endl;
    cout<<"---------------------------"<<endl;
    const int y=2;
    const int* cpy=&y;
    const int* const cpcy=&y;
    auto ay=y;
    auto acpy=cpy;
    auto acpcy=cpcy;
    auto&& aay=y;
    cout<<typeid(aay).name()<<endl;
    cout<<typeid(ay).name()<<endl;
    cout<<typeid(acpy).name()<<endl;
    cout<<typeid(acpcy).name()<<endl;
    cout<<"---------------------------"<<endl;

    int &rx=x;
    const int& cry=y;
    const int&& crrt=1+3;
    auto arx=rx;
    auto acry=cry;
    auto acrrt=crrt;
    cout<<typeid(arx).name()<<endl;
    cout<<typeid(acry).name()<<endl;
    cout<<typeid(acrrt).name()<<endl;
    cout<<"---------------------------"<<endl;

    decltype(x) dx=x;
    cout<<typeid(dx).name()<<endl;
    decltype((x)) ddx=x;
    cout<<typeid(ddx).name()<<endl;
    decltype(px) dpx=px;
    cout<<typeid(dpx).name()<<endl;
    decltype((px)) ddpx=px;
    cout<<typeid(ddpx).name()<<endl;
    decltype(cpx) dcpx=cpx;
    cout<<typeid(dcpx).name()<<endl;
    decltype((cpx)) ddcpx=cpx;
    cout<<typeid(ddcpx).name()<<endl;
    decltype(cpcx) dcpcx=cpcx;
    cout<<typeid(dcpcx).name()<<endl;
    decltype((cpcx)) ddcpcx=cpcx;
    cout<<typeid(ddcpcx).name()<<endl;
    decltype(rx) drx=rx;
    cout<<typeid(drx).name()<<endl;
    decltype((rx)) ddrx=rx;
    cout<<typeid(ddrx).name()<<endl;
    decltype(cry) dccry=cry;
    cout<<typeid(dccry).name()<<endl;
    decltype((cry)) ddcry=cry;
    cout<<typeid(ddcry).name()<<endl;
    decltype(1+2) dt=3;
    cout<<typeid(dt).name()<<endl;
    decltype((1+2)) dt2=5;
    cout<<typeid(dt2).name()<<endl;

    return 0;
}